昨天我們開發了第一個小專案:待辦事項,經過簡單的操作,我們完成了待辦事項的簡單展示,結合例項學習了 nz-table
元件的使用方式,儘管沒有涉及到全部屬性,但是我們已經可以讓一個 table
元件正常工作了。
今天我們會繼續對 待辦事項(TODO)進行優化,補全 建立任務
、修改任務
和 刪除任務
等操作。
開始之前同樣地,請大家先下載 github 程式碼啟動後開啟 http://localhost:4200 預覽
$ git clone https://github.com/simplejason/ng-zorro-ironman2020.git
$ cd ng-zorro-ironman2020 && npm i
$ ng serve
我們今天需要完成建立、修改、刪除操作,先來看一下預覽圖
上文我們已經完成了顯示待辦事項的列表,想必大家還記得昨天我們在頁面上留了一個 新增任務
的按鈕,現在就讓我們來實現這個功能。既然是建立,我們就決定使用 form
元件來實現,NG-ZORRO 也為我們提供了改元件 nz-form
:
表單排列方式
最簡結構
<form nz-form>
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="email">E-mail</nz-form-label>
<nz-form-control [nzSpan]="14">
<input nz-input name="email" type="email" id="email">
</nz-form-control>
</nz-form-item >
</form>
form
元件同樣遵循 ant design
設計規範,對於錯誤情況、佈局、校驗等都提供了相應的API,我們今天也會使用這些屬性來看看它的設計。
暫時我們為了簡潔都是直接通過變數陣列的變化來展示,大家可以嘗試使用 localStorage 來儲存相應的資料。
為了便於開發,我們使用 Reactive Forms
來建立,我們之前給 task
任務設定了一個 interface
格式
export interface ITask {
id: number;
name: string;
description: string;
isDone?: boolean;
deadline: Date;
}
這樣我們就很容易建立,進入到 todo.component.ts
,
export class TodoComponent implements OnInit {
createForm: FormGroup;
constructor(
private fb: FormBuilder
) {
this.createForm = this.fb.group({
name : [ null, [ Validators.required ] ],
description: [ null ],
isDone : [ false ],
deadline : [ new Date() ]
});
}
}
我們在頁面上直接使用 nz-form
來建立一個表單,進入 todo.component.html
建立表單,這樣一個可輸入的表單就完成了。(stackblitz 線上程式碼)
<form nz-form [formGroup]="createForm">
<nz-form-item>
<nz-form-control nzErrorTip="請輸入名稱">
<nz-input-group nzCompact>
<input class="form-name" type="text" nz-input placeholder="例如:今天八點前更新鐵人賽文章" formControlName="name"/>
<nz-date-picker
formControlName="deadline"
nzFormat="MMMMd日 HH:mm"
[nzShowTime]="{ nzFormat: 'HH:mm' }"
[nzDisabledDate]="disabledDate"
></nz-date-picker>
</nz-input-group>
</nz-form-control>
</nz-form-item>
</form>
可以看到我們很容易就建立了一個建立任務的表單,讓我們加上按鈕來美化一下,看一下效果
對應的建立任務事件也很容易書寫
addTask(): void {
// 驗證form狀態
for (const i in this.createForm.controls) {
this.createForm.controls[ i ].markAsDirty();
this.createForm.controls[ i ].updateValueAndValidity();
}
if (this.createForm.valid) {
const newTask = {
...this.createForm.getRawValue(),
id: new Date().getTime()
};
// 更新待辦陣列
this.listOfTodoTasks = this.listOfTodoTasks.concat([ newTask ]);
// reset after adding new task
this.createForm.get('name').reset();
this.nzMessageService.success('成功建立了一個任務,記得完成喔!');
}
}
PS:我們之前說了,nz-form
支援錯誤提示,只需要我們在 nz-form-control
上新增 nzErrorTip
屬性即可實現錯誤提示,參考 這個示例 來感受一下。
既然建立都完成了,我們自然需要修改任務,比如需要切換完成時間、任務名稱等等操作,在這裡我們採用 nz-drawer
抽屜元件,我們先來看一個 線上的簡單 demo
<button nz-button nzType="primary" (click)="open()">Open</button>
<nz-drawer
[nzClosable]="false"
[nzVisible]="visible"
nzPlacement="right"
nzTitle="Basic Drawer"
(nzOnClose)="close()"
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</nz-drawer>
這裡直接通過 nz-drawer
元件的 nzVisible
屬性來控制是否顯示抽屜元件,不過我並不打算使用這種建立方式,因為這會導致我們的 html
檔案包含大量的複雜程式碼,使用 NzDrawerService
來建立是個更好地方案,它可以接受一個 component
作為渲染模板,這樣我們可以放心地將修改表單模組單獨以一個獨立元件來維護。
先看一下我們當前程式碼是如何寫的(Github Commit),在 todo.component.ts
中,我們將 TaskDetailComponent
作為顯示模板,傳遞 task
屬性使 TaskDetailComponent
能接收到要修改的任務資料, TaskDetailComponent
中呼叫 NzDrawerRef.close(data)
方法即可傳遞任意資料回來, this.drawerRef.afterClose
這個 Observable
就可以正常訂閱資料回顯,我們可以在這裡做一些特殊的操作。
在這種寫法和上面直接使用 nz-drawer
效果是一模一樣的,只是這種方式更加可維護。
showEditTask() {
this.drawerRef = this.nzDrawerService.create({
nzTitle : this.activatedTask.name,
nzContent : TaskDetailComponent,
nzWidth : 400,
nzContentParams: {
task: this.activatedTask
}
});
// 觸發關閉
this.drawerRef.afterClose.subscribe(task => {
if (task) {
this.listOfTodoTasks = this.listOfTodoTasks.map(v => {
if (v.id === task.id) {
v = task;
}
return v;
});
this.cdr.markForCheck();
this.nzMessageService.success('成功更新了這個任務!');
}
});
}
因為我們沒有通過 API 方式來管理資料,所以目前都是直接使用 filter
等陣列操作來完成,有興趣的同學可以自行建立一個 localStorage
操作的 service
來嘗試一下。
實際上今天我們僅僅是初步講解了 nz-form
和 nz-drawer
的使用方式,目前待辦事項結構也是比較簡單的 form
結構,現在我們還不需要使用太多複雜的表單結構,否則會使我們的專案程式碼十分冗餘和難以理解。新出現的 nz-date-picker
元件也會在下一章節詳細去介紹一下。
form
表單有很多值得關注的地方等到我們去探索,大家可以跟隨文章的進展逐步去接觸更加複雜也更加有意思的表單使用方式。
下一篇我們會繼續來完善待辦事項,我們會給待辦任務新增更多的屬性來讓這個專案豐富起來。